﻿package elements 
{
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	import gs.TweenLite;
	import styles.ButtonStyle;
	
	/**
	 * Обычная кнопка-обертка
	 * @author Kasoi
	 */
	public class Button extends Sprite 
	{
		
		////////////////////////////////////////////////////////////////////
		// Public properties
		////////////////////////////////////////////////////////////////////
		
		public function get image() : DisplayObject
		{
			return this._image;
		}
		
		public function get actionPhase() : Number 
		{
			return this._actionPhase;
		}
		
		public function set actionPhase(value: Number) : void 
		{
			this._actionPhase = value;
			
			var method: Function = this.style.actionAnimation;
			method(this._image, value);
		}
		
		public function get hoverPhase() : Number 
		{
			return this._hoverPhase;
		}
		
		public function set hoverPhase(value: Number) : void 
		{
			this._hoverPhase = value;
			
			var method: Function = this.style.hoverAnimation;
			method(this._image, value);
		}
		
		public function get triggerArea() : Rectangle
		{
			var rect: Rectangle = this.trigger.getRect(this.trigger);
			return rect;
		}
		
		public function set triggerArea(value: Rectangle) : void 
		{
			this.trigger.graphics.clear();
			this.trigger.graphics.beginFill(0xff00ff, 0.0);
			this.trigger.graphics.drawRect(value.x, value.y, value.width, value.height);
			this.trigger.graphics.endFill();
		}
		
		public function get disablePhase() : Number 
		{
			return this._disablePhase;
		}
		
		public function set disablePhase(value: Number) : void 
		{
			this._disablePhase = value;
			
			if (this._hoverPhase > 0)
			{
				this.hoverPhase = 1 - value;
			}
			
			var method: Function = this.style.disableAnimation;
			method(this._image, value);
		}
		
		////////////////////////////////////////////////////////////////////
		// Private properties
		////////////////////////////////////////////////////////////////////
		
		private var style: ButtonStyle;
		
		private var _image: DisplayObject;
		
		private var trigger: Sprite;
		
		private var _triggerScaleSize: Number = 1.4;
		
		private var body: Sprite;
		
		private var _hoverPhase: Number = 0;
		
		private var _actionPhase: Number = 0;
		
		private var _disablePhase: Number = 0;
		
		private var _isEnabled: Boolean = true;
		
		private var callMethod: Function;
		
		private var isPressed: Boolean = false;
		
		private var useTrigger: Boolean;
		
		////////////////////////////////////////////////////////////////////
		// Public methods
		////////////////////////////////////////////////////////////////////
		
		public function Button(image: DisplayObject, style: ButtonStyle = null,
			useTrigger: Boolean = true, callOnClick: Function = null) 
		{
			this._image = image;
			this.style = ((style == null) ? new ButtonStyle() : style);
			this.callMethod = callOnClick;
			this.useTrigger = useTrigger;
			
			var w: Number = image.width;
			var h: Number = image.height;
			var s: Number = this._triggerScaleSize;
			var px: Number = ((w * s) - w) / 2;
			var py: Number = ((h * s) - h) / 2;
			
			this.body = new Sprite();
			
			this.body.addChild(this._image);
			
			if (useTrigger)
			{
				this.trigger = new Sprite();
				this.trigger.graphics.beginFill(0xff00ff, 0.0);
				this.trigger.graphics.drawRect( 
					-px, -py, w + px * 2, h + py * 2);
				this.trigger.graphics.endFill();
				this.body.addChild(this.trigger);
			}
			
			this.addChild(this.body);
			
			this.body.buttonMode = true;
			
			this.addEventListener(Event.ADDED_TO_STAGE, this.onAddedToStage);
		}
		
		public function enable() : void 
		{
			//if (this._isEnabled) return;
			this._isEnabled = true;
			this.mouseChildren = this.mouseEnabled = true;
			
			TweenLite.to(this, this.style.disableTime, 
				{ disablePhase: 0, ease: this.style.disableEasing} );
		}
		
		public function disable() : void 
		{
			this._isEnabled = false;
			this.mouseChildren = this.mouseEnabled = false;
			
			TweenLite.to(this, this.style.disableTime, 
				{ disablePhase: 1, ease: this.style.disableEasing} );
		}
		
		////////////////////////////////////////////////////////////////////
		// Private methods
		////////////////////////////////////////////////////////////////////
		
		private function addListeners() : void 
		{
			this.body.addEventListener(MouseEvent.MOUSE_DOWN, this.body_onMouseDown);
			this.body.addEventListener(MouseEvent.MOUSE_OVER, this.body_onMouseOver);
			this.body.addEventListener(MouseEvent.MOUSE_OUT, this.body_onMouseOut);
			this.body.addEventListener(MouseEvent.CLICK, this.body_onClick);
		}
		
		private function removeListeners() : void 
		{
			this.body.removeEventListener(MouseEvent.MOUSE_DOWN, this.body_onMouseDown);
			this.body.removeEventListener(MouseEvent.MOUSE_OVER, this.body_onMouseOver);
			this.body.removeEventListener(MouseEvent.MOUSE_OUT, this.body_onMouseOut);
			this.removeEventListener(Event.ADDED_TO_STAGE, this.onAddedToStage);
			this.body.removeEventListener(MouseEvent.CLICK, this.body_onClick);
		}
		
		////////////////////////////////////////////////////////////////////
		// Listeners
		////////////////////////////////////////////////////////////////////
		
		private function onAddedToStage(e: Event) : void 
		{
			this.addListeners();
		}
		
		private function body_onMouseDown(e: MouseEvent) : void 
		{
			this.isPressed = true;
			stage.addEventListener(MouseEvent.MOUSE_UP, this.body_onMouseUp);
			if (!this._isEnabled) return;
			TweenLite.to(this, this.style.actionTime, 
				{ actionPhase: 1, ease: this.style.actionEaseing } );
		}
		
		private function body_onMouseUp(e: MouseEvent) : void 
		{
			this.isPressed = false;
			if (stage)
			{
				stage.removeEventListener(MouseEvent.MOUSE_UP, this.body_onMouseUp);
			}
			if (!this._isEnabled) return;
			
			var mx: Number = this.mouseX;
			var my: Number = this.mouseY;
			var y: Number = 0;// this.x;
			var x: Number = 0;// this.y;
			var w: Number = this.width;
			var h: Number = this.height;
			
			if (this.useTrigger)
			{
				x = this.trigger.x;
				y = this.trigger.y;
				w = this.trigger.width;
				h = this.trigger.height;
			}
			
			if (mx > x && my > y && mx < x + w && my < y + h) 
			{
				TweenLite.to(this, this.style.hoverTime,
					{actionPhase: 0, hoverPhase: 1, ease: this.style.actionEaseing } );
				return;
			}
			else
			{
				TweenLite.to(this, this.style.actionTime, 
					{ hoverPhase: 0, actionPhase: 0, ease: this.style.actionEaseing } );
			}
		}
		
		private function body_onMouseOver(e: MouseEvent) : void 
		{
			if (this.isPressed) return;
			if (!this._isEnabled) return;
			TweenLite.to(this, this.style.hoverTime, 
				{ hoverPhase: 1, ease: this.style.hoverEasing } );
		}
		
		private function body_onMouseOut(e: MouseEvent) : void 
		{
			if (this.isPressed) return;
			if (!this._isEnabled) return;
			TweenLite.to(this, this.style.hoverTime, 
				{ hoverPhase: 0, ease: this.style.hoverEasing } );
		}
		
		private function body_onClick(e: MouseEvent) : void 
		{
			if (this.callMethod != null) this.callMethod();
		}
	}
	
}